﻿// Inner Fire 游戏引擎库
// 通用的定义
//
// Copyright (c) 2025 by 尔西大帝. All rights reserved.
//
// 对于项目中都通用的定义。比如FrameCount，每个引擎应该是3个。
//
// Author: 尔西大帝
// Email: 2670613871@qq.com
// Created: 2025-03-22

#pragma once

#include <DirectXMath.h>
#include <static_string.h>

namespace ifire {

enum IAxis { X, Y, Z };
IAxis ParseIAxis(ikit::sstr name, IAxis default_value = IAxis::X);

// 得到一个单位矩阵
extern const DirectX::XMFLOAT4X4 IDENTITY_4X4;
extern const DirectX::XMFLOAT3X3 IDENTITY_3X3;
extern const DirectX::XMFLOAT3X3 ZERO_3X3;
// 用于0的计算
extern const DirectX::XMMATRIX ZERO_MAT;
extern const DirectX::XMMATRIX ID_MAT;
// 默认的缩放（1.0,1.0,1.0,0.0f）
extern const DirectX::XMVECTOR SCALE1;
// 0值
extern const DirectX::XMVECTOR VEC0;
// 单位四元数（无旋转）
extern const DirectX::XMVECTOR ID_QUAT;

// UINT的最大值，用于索引是否使用32位的判断。-1是留一个位置。返回1两个索引也不差。
constexpr unsigned int MAX_UINT_16 = 65535 - 1;
// 帧资源的数量
constexpr int FRAME_RESOURCE_COUNT = 3;
// 交换链的数量，通常是2个。
constexpr unsigned int SWAP_CHAIN_BUFFER_COUNT = 2;

// 圆周率
constexpr float PI = 3.1415926535f;

// 度数弧度转换
constexpr float DEG_TO_RAD = 180.0f / PI;
constexpr float RAD_TO_DEG = PI / 180.0f;

// 从1cm转到1m的单位变换。
constexpr float UNIT_SCALE = 0.01f;

// 用于比较
constexpr const float F_EPSILON = 1e-6F;
extern const DirectX::XMVECTOR VEC_EPSILON;

// 计算缓冲区的大小，需要和256字节对齐
constexpr static size_t calc_constant_buffer_size(size_t origin_byte_size) {
  return (origin_byte_size + 255) & ~255;
}

using IMat = DirectX::XMMATRIX;
using IVec = DirectX::XMVECTOR;
using IVec2 = DirectX::XMFLOAT2;
using IVec3 = DirectX::XMFLOAT3;

using IQuat = DirectX::XMVECTOR;
using IVec4 = DirectX::XMFLOAT4;
using IMat3 = DirectX::XMFLOAT3X3;
using IMat4 = DirectX::XMFLOAT4X4;
using FMat3 = const DirectX::XMFLOAT3X3&;
using FMat4 = const DirectX::XMFLOAT4X4&;
using FMat = const DirectX::XMMATRIX&;
using FQuat = const DirectX::XMVECTOR&;
using FVec = const DirectX::XMVECTOR&;

// 用于打印项目printf时，不需要设置每个项目的分量，直接使用这个
#define VEC_PF(v) v.m128_f32[0], v.m128_f32[1], v.m128_f32[2]

// 用于返回一个项目
// XMVECTOR -> XMFLOAT3 转换 (零开销)
inline DirectX::XMFLOAT3 StoreF3(DirectX::XMVECTOR v) noexcept {
  DirectX::XMFLOAT3 ret;
  DirectX::XMStoreFloat3(&ret, v);
  return ret;
}

// XMVECTOR -> XMFLOAT4 转换
inline DirectX::XMFLOAT4 StoreF4(DirectX::XMVECTOR v) noexcept {
  DirectX::XMFLOAT4 ret;
  DirectX::XMStoreFloat4(&ret, v);
  return ret;
}

inline DirectX::XMFLOAT3X3 StoreM3(DirectX::XMMATRIX v) noexcept {
  DirectX::XMFLOAT3X3 ret;
  DirectX::XMStoreFloat3x3(&ret, v);
  return ret;
}
// 高性能加法（无分支、无动态分配）
inline void AddF3(
    DirectX::XMFLOAT3& lhs, const DirectX::XMFLOAT3& rhs) noexcept {
  lhs.x += rhs.x;
  lhs.y += rhs.y;
  lhs.z += rhs.z;
}

} // namespace ifire